package com.nwpu.am.controller.common;

import com.nwpu.am.constant.ErrorConstant;
import com.nwpu.am.constant.JwtClaimsConstant;
import com.nwpu.am.constant.properties.JwtProperties;
import com.nwpu.am.constant.properties.RedisProperties;
import com.nwpu.am.pojo.dto.UserLoginDTO;
import com.nwpu.am.pojo.entity.User;
import com.nwpu.am.pojo.vo.UserLoginVO;
import com.nwpu.am.result.Result;
import com.nwpu.am.service.UserService;
import com.nwpu.am.utils.JwtUtil;
import com.nwpu.am.utils.ThreadLocalUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

/**
 * CommonController
 *
 * @author Roy
 * @version 1.0
 * {@code @date} 2024/6/3
 */

@RestController
@RequestMapping("/common")
@Slf4j
@Api(tags = "员工通用接口")
public class CommonController {
    @Resource
    private UserService userService;
    @Resource
    private JwtProperties jwtProperties;
    @Resource
    private RedisProperties redisProperties;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @PostMapping("/login")
    @ApiOperation("登录接口")
    public Result<UserLoginVO> login(@RequestBody @Validated UserLoginDTO userLoginDTO) {
        // 验证用户名和密码
        User user = userService.findByUsername(userLoginDTO.getUsername());
        if (user == null) {
            return Result.error(ErrorConstant.USER_NOT_FIND);
        }

        // 通过shiro验证用户名和密码
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userLoginDTO.getUsername(), userLoginDTO.getPassword());
        try {
            log.info(usernamePasswordToken.getCredentials().toString());
            subject.login(usernamePasswordToken);
        } catch (Exception e) {
            log.error(e.getMessage());
            return Result.error(ErrorConstant.WRONG_PASSWORD);
        }

        // 脱敏
        user.setPassword(null);
        // 储存登录态信息
        ThreadLocalUtil.set(user);

        // 生成jwt令牌
        HashMap<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.USER_INFO, user);
        String token = JwtUtil.createJWT(
                jwtProperties.getUserSecretKey(),
                jwtProperties.getUserTtl(),
                claims
        );
        // 把token存储在redis中
        ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
        operations.set(token, token, redisProperties.getRedisTtl(), TimeUnit.HOURS);

        log.info("用户登录user：{}", user.getUsername());
        return Result.success(UserLoginVO.userCopy(user, token));
    }

    @PostMapping("/logout")
    @ApiOperation("登出接口")
    @RequiresPermissions("common:logout")
    public Result<String> logout(@RequestHeader("Authorization") String token) {
        log.info("用户登出user：{}", ThreadLocalUtil.get().toString());
        // 删除登录态
        if (ThreadLocalUtil.get() != null) {
            ThreadLocalUtil.remove();
        }
        // 删除redis信息
        ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
        if (operations.get(token) != null) {
            operations.getOperations().delete(token);
        }
        return Result.success();
    }
}
